﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.IO.Compression;

namespace Weather.Core
{
    public class Forecast
    {
        public string Date { get; set; }
        public string High { get; set; }
        public string Low { get; set; }
        public string Type { get; set; }
        public string FengXiang { get; set; }
        public string Fengli { get; set; }
    }
    public class Env
    {
        /// <summary>
        /// 空气质量指数
        /// </summary>
        public int AQI { get; set; }
        /// <summary>
        /// PM2.5浓度
        /// </summary>
        public int PM25 { get; set; }
        /// <summary>
        /// 建议
        /// </summary>
        public string Suggest { get; set; }
        /// <summary>
        /// 空气质量等级
        /// </summary>
        public string Quality { get; set; }
    }

    public class ZhiShu
    {
        /// <summary>
        /// 指数名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 指数值
        /// </summary>
        public string Value { get; set; }
        /// <summary>
        /// 指数详情
        /// </summary>
        public string Detail { get; set; }
    }
    /// <summary>
    /// 天气数据
    /// </summary>
    public class WeatherData
    {
        /// <summary>
        /// 城市名称
        /// </summary>
        public string CityName { get; set; }
        /// <summary>
        /// 温度
        /// </summary>
        public string WenDu { get; set; }
        /// <summary>
        /// 风力
        /// </summary>
        public string Fengli { get; set; }
        /// <summary>
        /// 湿度
        /// </summary>
        public string ShiDu { get; set; }
        /// <summary>
        /// 风向
        /// </summary>
        public string FengXiang { get; set; }
        /// <summary>
        /// 环境指数
        /// </summary>
        public Env Environment { get; set; }
        /// <summary>
        /// 天气预报
        /// </summary>
        public List<Forecast> ForecastList { get; set; }
        /// <summary>
        /// 指数列表
        /// </summary>
        public List<ZhiShu> ZhiShuList { get; set; }
        /// <summary>
        /// 更新时间
        /// </summary>
        public string UpdateTime { get; set; }
    }
    public class WeatherAPI
    {
        private const string API = "http://wthrcdn.etouch.cn/WeatherApi?city=";
        private string cityName;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="cityName">城市名称</param>
        public WeatherAPI(string cityName)
        {
            this.cityName = cityName;
        }
        /// <summary>
        /// 获取天气
        /// </summary>
        /// <returns>天气数据</returns>
        public WeatherData GetCityWeatherData()
        {
            return ParseData(GetXmlByUrl(API + this.cityName));
        }

        /// <summary>
        /// 根据城市名字获取天气
        /// </summary>
        /// <param name="cityName">城市名字</param>
        /// <returns>天气数据</returns>
        public WeatherData GetCityWeatherData(string cityName)
        {
            this.cityName = cityName;
            return ParseData(GetXmlByUrl(API + cityName));
        }

        private WeatherData ParseData(XmlDocument xml)
        {

            XmlNode root = xml.DocumentElement;
            WeatherData w = new WeatherData();
            w.CityName = root["city"].InnerText;
            w.UpdateTime = root["updatetime"].InnerText;
            w.WenDu = root["wendu"].InnerText;
            w.ShiDu = root["shidu"].InnerText;
            w.Fengli = root["fengli"].InnerText;
            w.FengXiang = root["fengxiang"].InnerText;
            Env env = new Env();
            List<Forecast> forecastList = new List<Forecast>();
            List<ZhiShu> zsList = new List<ZhiShu>();
            w.Environment = env;
            w.ForecastList = forecastList;
            w.ZhiShuList = zsList;
            XmlElement envNode = root["environment"];
            env.AQI = int.Parse(envNode["aqi"].InnerText);
            env.PM25 = int.Parse(envNode["pm25"].InnerText);
            env.Quality = envNode["quality"].InnerText;
            env.Suggest = envNode["suggest"].InnerText;
            XmlElement forecastNode = root["forecast"];
            foreach (XmlElement item in forecastNode.ChildNodes)
            {
                Forecast f = new Forecast();
                f.Date = item["date"].InnerText;
                f.Low = item["low"].InnerText;
                f.High = item["high"].InnerText;

                f.Fengli = item["day"]["fengli"].InnerText;
                f.FengXiang = item["day"]["fengxiang"].InnerText;
                f.Type = item["day"]["type"].InnerText;
                forecastList.Add(f);
            }
            XmlElement zhishuNode = root["zhishus"];
            foreach (XmlElement item in zhishuNode.ChildNodes)
            {
                ZhiShu zs = new ZhiShu();
                zs.Detail = item["detail"].InnerText;
                zs.Name = item["name"].InnerText;
                zs.Value = item["value"].InnerText;
                zsList.Add(zs);
            }
            return w;
        }
        private WeatherData ParseData(string data)
        {
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(data);
            return ParseData(xml);
        }


        private XmlDocument GetXmlByUrl(string url)
        {
            WebClient client = new WebClient();
            MemoryStream ms = new MemoryStream(Decompress(client.DownloadData(url)));
            XmlTextReader rdr = new XmlTextReader(ms);
            XmlDocument xml = new XmlDocument();
            xml.Load(rdr);
            return xml;
        }
        public static byte[] Decompress(byte[] zippedData)
        {
            MemoryStream ms = new MemoryStream(zippedData);
            GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Decompress);
            MemoryStream outBuffer = new MemoryStream();
            byte[] block = new byte[1024];
            while (true)
            {
                int bytesRead = compressedzipStream.Read(block, 0, block.Length);
                if (bytesRead <= 0)
                    break;
                else
                    outBuffer.Write(block, 0, bytesRead);
            }
            compressedzipStream.Close();
            return outBuffer.ToArray();
        }

        private string GetHttpData(string url)
        {
            Console.WriteLine("开始获取{0}的天气数据...", this.cityName);
            WebRequest request = WebRequest.Create(url);
            request.Method = "GET";
            using (WebResponse answer = request.GetResponse())
            {
                using (Stream s = answer.GetResponseStream())
                {
                    
                    StreamReader reader = new StreamReader(s, Encoding.Default);
                    string content = reader.ReadToEnd();
                    Console.WriteLine(content);
                    return content;
                }
            }
        }
    }
}
